const canvas = document.getElementById('textureCanvas');
const ctx = canvas.getContext('2d')

//Resize the canvas.
const getPowerOfTwo = (value, pow) => {
    let pow1 = pow || 1;
    while (pow1 < value) {
        pow1 *= 2;
    }
    return pow1;
}

//Measure the length of the text.
const measureText = (ctx, textToMeasure) => {
    return ctx.measureText(textToMeasure).width;
}


const createMultilineText = (ctx, textToWrite, maxWidth, text) => {
    textToWrite = textToWrite.replace("\n", " ");
    let currentText = textToWrite;
    let futureText;
    let subWidth = 0;
    let maxLineWidth = 0;

    let wordArray = textToWrite.split(" ");
    let wordsInCurrent, wordArrayLength;
    wordsInCurrent = wordArrayLength = wordArray.length;

    while (measureText(ctx, currentText) > maxWidth && wordsInCurrent > 1) {
        wordsInCurrent--;
        let linebreak = false;

        currentText = futureText = "";
        for (let i = 0; i < wordArrayLength; i++) {
            if (i < wordsInCurrent) {
                currentText += wordArray[i];
                if (i + 1 < wordsInCurrent) {
                    currentText += " ";
                }
            } else {
                futureText += wordArray[i];
                if (i + 1 < wordArrayLength) {
                    futureText += " ";
                }
            }
        }
    }
    text.push(currentText);
    maxLineWidth = measureText(ctx, currentText);

    if (futureText) {
        subWidth = createMultilineText(ctx, futureText, maxWidth, text);
        if (subWidth > maxLineWidth) {
            maxLineWidth = subWidth;
        }
    }

    return maxLineWidth;
}

const drawText = () => {
    let canvasX, canvasY;
    let textX, textY;
    let text = [];
    let textToWrite = '你好';
    let maxWidth = parseInt(256, 10);
    let squareTexture = true;
    let textHeight = 128;
    let textAlignment = extX = canvasX / 2;
    let textColour = 'red';
    let fontFamily = 'monospace';
    let backgroundColour = '#9b729c';
    ctx.font = textHeight + "px " + fontFamily;

    if (maxWidth && measureText(ctx, textToWrite) > maxWidth) {
        maxWidth = createMultilineText(ctx, textToWrite, maxWidth, text);
        canvasX = getPowerOfTwo(maxWidth);
    } else {
        text.push(textToWrite);
        canvasX = getPowerOfTwo(ctx.measureText(textToWrite).width);
    }

    canvasY = getPowerOfTwo(textHeight * (text.length + 1));
    if (squareTexture) {
        (canvasX > canvasY) ? canvasY = canvasX: canvasX = canvasY;
    }

    canvas.width = canvasX;
    canvas.height = canvasY;

    textX = 0;
    textY = canvasY / 2;






    ctx.fillStyle = textColour;
    ctx.textAlign = textAlignment;

    ctx.textBaseline = 'middle'; // top, middle, bottom
    ctx.font = textHeight + "px " + fontFamily;

    let offset = (canvasY - textHeight * (text.length + 1)) * 0.5;

    for (let i = 0; i < text.length; i++) {
        if (text.length > 1) {
            textY = (i + 1) * textHeight + offset;
        }
        ctx.fillText(text[i], textX, textY);
    }
}

drawText()

var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'attribute vec2 a_TexCoord;\n' +
    'varying vec2 v_TexCoord;\n' +
    'void main() {\n' +
    '   gl_Position = a_Position;\n' +
    '   v_TexCoord = a_TexCoord;\n' +
    '}\n';


var FSHADER_SOURCE =
    '#ifdef GL_ES\n' +
    'precision mediump float;\n' +
    '#endif\n' +
    'uniform sampler2D u_Sampler;\n' +
    'varying vec2 v_TexCoord;\n' +
    'void main() {\n' +
    '  gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n' +
    '}\n';


const initVertexBuffers = (gl) => {
    var verticesTexCoords = new Float32Array([-0.10, 0.10, 0, 1, -0.10, -0.10, 0, 0,
        0.10, 0.10, 1, 1,
        0.10, -0.10, 1, 0
    ]);
    var n = 4;


    var vertexTexCoordBuffer = gl.createBuffer();


    if (!vertexTexCoordBuffer) {
        console.log('Failed to create the vertexTexCooredBuffer object ');
        return -1;
    }


    gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

    var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;


    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

    if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }


    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);


    gl.enableVertexAttribArray(a_Position);



    var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');

    if (a_TexCoord < 0) {
        console.log('Failed to get the storage location of a_TexCoord');
        return -1;
    }
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
    gl.enableVertexAttribArray(a_TexCoord); // 开启缓冲区分配

    return n
}

const initTextures = (gl) => {
    let canvasTexture = gl.createTexture();


    if (!canvasTexture) {
        console.log('Failed to create the texture object');
        return false;
    }

    let u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');

    if (!u_Sampler) {
        console.log('Failed to get the storage location of u_Sampler');
        return false;
    }

    handleLoadedTexture(gl, canvasTexture, document.getElementById('textureCanvas'), u_Sampler);

    return true

}

const handleLoadedTexture = (gl, texture, textureCanvas, u_Sampler) => {
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);

    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvas); // This is the important line!
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.uniform1i(u_Sampler, 0)
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
}


const main = () => {

    let webglCanvas = document.getElementById('webglCanvas');


    let gl = getWebGLContext(webglCanvas);

    if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
    }


    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed to initialize shaders');
        return;
    }


    var n = initVertexBuffers(gl);
    gl.enable(gl.BLEND);

    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);


    if (n < 0) {
        console.log('Failed to set the positions of the vertices');
        return;
    }


    gl.clearColor(0.0, 0.0, 1.0, 1.0);

    if (!initTextures(gl, n)) {
        console.log('Failed to intialize the texture.');
        return;
    }
}

main()